package com.campus.backend.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.campus.backend.bean.coupon.CouponQueryParam;
import com.campus.backend.bean.coupon.CreateCouponBean;
import com.campus.backend.bean.coupon.UpdateCouponBean;
import com.campus.backend.entity.Coupon;
import com.campus.backend.entity.UserCoupon;
import com.campus.backend.mapper.CouponMapper;
import com.campus.backend.mapper.UserCouponMapper;
import com.campus.backend.vo.coupon.CouponVo;
import com.campus.common.bean.common.PageUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 优惠券表 服务实现类
 * </p>
 *
 * @author ZhaoYuJie
 * @since 2025-05-21
 */
@Service
public class CouponService extends ServiceImpl<CouponMapper, Coupon> {
    @Autowired
    private UserCouponMapper userCouponMapper;

    /**
     * 分页查询优惠券列表
     *
     * @param param 查询参数
     * @return 分页结果
     */
    public PageInfo<CouponVo> getCouponListPage(CouponQueryParam param) {
        PageInfo<Coupon> pageInfo = PageHelper.startPage(param.getPageNo(), param.getPageSize())
                .doSelectPageInfo(() -> this.getCouponDataList(param));

        // 转换为VO对象并设置是否已发放字段
        List<CouponVo> voList = pageInfo.getList().stream().map(coupon -> {
            CouponVo vo = new CouponVo();
            BeanUtil.copyProperties(coupon, vo);
            vo.setIsIssued(isCouponIssued(coupon.getId()));
            return vo;
        }).collect(Collectors.toList());

        return PageUtil.convertPageInfo(pageInfo, voList);
    }

    private List<Coupon> getCouponDataList(CouponQueryParam param) {
        LambdaQueryWrapper<Coupon> queryWrapper = new LambdaQueryWrapper<>();
        
        // 优惠券名称模糊查询
        if (StrUtil.isNotBlank(param.getName())) {
            queryWrapper.like(Coupon::getName, param.getName());
        }
        
        // 优惠券类型
        if (param.getType() != null) {
            queryWrapper.eq(Coupon::getType, param.getType());
        }
        
        // 状态
        if (param.getStatus() != null) {
            queryWrapper.eq(Coupon::getStatus, param.getStatus());
        }
        
        // 发放类型
        if (param.getIssueType() != null) {
            queryWrapper.eq(Coupon::getIssueType, param.getIssueType());
        }
        
        // 发放条件
        if (StrUtil.isNotBlank(param.getIssueCondition())) {
            queryWrapper.eq(Coupon::getIssueCondition, param.getIssueCondition());
        }
        
        // 时间范围查询
        if (StrUtil.isNotBlank(param.getStartTimeBegin())) {
            queryWrapper.ge(Coupon::getUseStartTime, param.getStartTimeBegin());
        }
        if (StrUtil.isNotBlank(param.getStartTimeEnd())) {
            queryWrapper.le(Coupon::getUseStartTime, param.getStartTimeEnd());
        }
        
        // 按创建时间倒序
        queryWrapper.orderByDesc(Coupon::getCreateTime);
        
        return this.list(queryWrapper);
    }

    /**
     * 根据ID获取优惠券详情
     *
     * @param couponId 优惠券ID
     * @return 优惠券详情
     */
    public CouponVo getCouponById(Integer couponId) {
        Coupon coupon = this.getById(couponId);
        if (coupon == null) {
            return null;
        }
        
        CouponVo vo = new CouponVo();
        BeanUtil.copyProperties(coupon, vo);
        vo.setIsIssued(isCouponIssued(coupon.getId()));
        return vo;
    }

    /**
     * 创建优惠券
     *
     * @param createCouponBean 优惠券信息
     * @return 优惠券ID
     */
    public Integer createCoupon(CreateCouponBean createCouponBean) {
        Coupon coupon = new Coupon();
        BeanUtil.copyProperties(createCouponBean, coupon);
        
        // 设置创建时间和更新时间
        LocalDateTime now = LocalDateTime.now();
        coupon.setCreateTime(now);
        coupon.setUpdateTime(now);
        
        // 设置默认状态为正常
        if (coupon.getStatus() == null) {
            coupon.setStatus(1);
        }
        
        // 设置剩余数量等于发行量
        coupon.setRemain(coupon.getTotal());
        
        this.save(coupon);
        return coupon.getId();
    }

    /**
     * 更新优惠券
     *
     * @param updateCouponBean 优惠券信息
     */
    public void updateCoupon(UpdateCouponBean updateCouponBean) {
        // 检查优惠券是否已被领取
        if (isCouponIssued(updateCouponBean.getId())) {
            throw new RuntimeException("优惠券已被领取，不能修改核心信息");
        }
        
        Coupon coupon = new Coupon();
        BeanUtil.copyProperties(updateCouponBean, coupon);
        
        // 检查优惠券是否存在
        Coupon existingCoupon = this.getById(coupon.getId());
        if (existingCoupon == null) {
            throw new RuntimeException("优惠券不存在");
        }
        
        // 设置更新时间
        coupon.setUpdateTime(LocalDateTime.now());
        
        // 如果修改了发行量，需要同步更新剩余数量
        int issued = existingCoupon.getTotal() - existingCoupon.getRemain();
        coupon.setRemain(coupon.getTotal() - issued);
        
        this.updateById(coupon);
    }

    /**
     * 删除优惠券
     *
     * @param couponId 优惠券ID
     */
    public void deleteCoupon(Integer couponId) {
        // 检查优惠券是否存在
        Coupon coupon = this.getById(couponId);
        if (coupon == null) {
            throw new RuntimeException("优惠券不存在");
        }
        
        // 检查是否可以删除（业务规则：已被领取的优惠券不能删除）
        if (isCouponIssued(couponId)) {
            throw new RuntimeException("该优惠券已被用户领取，无法删除");
        }
        
        this.removeById(couponId);
    }

    /**
     * 批量删除优惠券
     *
     * @param couponIds 优惠券ID列表
     */
    public void batchDeleteCoupon(List<Integer> couponIds) {
        // 检查每个优惠券是否可以删除
        for (Integer couponId : couponIds) {
            Coupon coupon = this.getById(couponId);
            if (coupon != null && isCouponIssued(couponId)) {
                throw new RuntimeException("优惠券【" + coupon.getName() + "】已被用户领取，无法删除");
            }
        }
        
        this.removeByIds(couponIds);
    }

    /**
     * 检查优惠券是否已被领取（公共方法）
     *
     * @param couponId 优惠券ID
     * @return 是否已被领取
     */
    public boolean isCouponIssued(Integer couponId) {
        LambdaQueryWrapper<UserCoupon> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserCoupon::getCouponId, couponId);
        queryWrapper.last("LIMIT 1");
        
        return userCouponMapper.selectCount(queryWrapper) > 0;
    }

    /**
     * 获取优惠券已领取数量
     *
     * @param couponId 优惠券ID
     * @return 已领取数量
     */
    private int getIssuedCount(Integer couponId) {
        LambdaQueryWrapper<UserCoupon> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserCoupon::getCouponId, couponId);
        
        return Math.toIntExact(userCouponMapper.selectCount(queryWrapper));
    }
}
